package com.xianniu.ltc.service.impl;

import cn.devezhao.bizz.security.member.NoMemberFoundException;
import cn.devezhao.commons.web.ServletUtils;
import cn.devezhao.persist4j.Entity;
import cn.devezhao.persist4j.engine.ID;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONAware;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.gson.JsonObject;
import com.rebuild.core.Application;
import com.rebuild.core.BootEnvironmentPostProcessor;
import com.rebuild.core.UserContextHolder;
import com.rebuild.core.metadata.EntityHelper;
import com.rebuild.core.metadata.MetadataHelper;
import com.rebuild.core.privileges.UserService;
import com.rebuild.core.privileges.bizz.User;
import com.rebuild.core.service.query.ParseHelper;
import com.rebuild.core.support.general.DataListBuilder;
import com.rebuild.core.support.general.DataListBuilderImpl;
import com.xianniu.ltc.mapper.TProjectDetailMapper;
import com.xianniu.ltc.mapper.TProjectMapper;
import com.xianniu.ltc.mapper.TProjectReportMapper;
import com.xianniu.ltc.mapper.TProjectUserlMapper;
import com.xianniu.ltc.model.entity.TProjectDTO;
import com.xianniu.ltc.model.entity.TProjectDetailDTO;
import com.xianniu.ltc.model.entity.TProjectReportDTO;
import com.xianniu.ltc.model.entity.TProjectUserDTO;
import com.xianniu.ltc.model.po.*;
import com.xianniu.ltc.model.vo.project.*;
import com.xianniu.ltc.service.ProjectService;
import com.xianniu.ltc.service.XnIconConfigService;
import com.xxl.sso.core.entity.ReturnT;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.poi.ss.formula.functions.T;
import org.apache.skywalking.apm.toolkit.trace.ActiveSpan;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.w3c.dom.EntityReference;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.stream.Collectors;

/**
 * @author WangRuiJie
 * @Title: ProjectService
 * @Package com.xianniu.ltc.service
 * @Description: 项目服务类
 * @date 2021/5/314:58 下午
 */
@Slf4j
@Service
public class ProjectServiceImpl implements ProjectService {

    @Value("${H5-URL}")
    private String h5Url;
    @Autowired
    private TProjectMapper tProjectMapper;
    @Autowired
    private TProjectDetailMapper tProjectDetailMapper;
    @Autowired
    private TProjectUserlMapper tProjectUserlMapper;
    @Autowired
    private XnIconConfigService iconConfigService;
    @Resource
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;
    @Autowired
    private TProjectReportMapper tProjectReportMapper;

    /**
     * 方案集合
     */
    public static final List<String> PLAN_LIST = Arrays.asList("shouqianxietong28","toubiaoxietong","baojiaxietong","shouqianfangan","Quotation");
    /**
     * 合约集合
     */
    public static final List<String> CONTRACT_LIST = Arrays.asList("kuangjiaxieyi","rbhetong0","buchongxieyixiaoshou","kuangjiaxieyi85","xiangmuhetong","buchongxieyicaigou");
    /**
     * 财务集合
     */
    public static final List<String> FINANCIAL_LIST = Arrays.asList("huikuanjihua","shoukuanliushui","fukuanjihua","rbfenyong3","xiangmujilineibu");
    /**
     * 销售阶段申请
     */
    public static final List<String> SALE_APPROVAL_LIST = Arrays.asList("teshujiageshenpi","rbyujiaofu5","yongzhangshenpi");
    /**
     * 合同及交付申请
     */
    public static final List<String> DELIVERY_APPROVAL_LIST = Arrays.asList("hetongshenpi","caigouguanli","fenbaoshenpi");
    /**
     * 收/支申请
     */
    public static final List<String> PAY_APPROVAL_LIST = Arrays.asList("xiangmuleibaoxiaoshenpi","xiangmuleifukuan","rbkaipiao0");

    @Override
    public ReturnT projectPage(ProjectQueryPO param) {
        QueryWrapper<TProjectDetailDTO> queryWrapper = new QueryWrapper<>();
        List<TProjectDetailDTO> detailDTOS = tProjectDetailMapper.selectList(queryWrapper);
        if(CollectionUtils.isNotEmpty(detailDTOS)){
            // 筛选可以访问的记录
            List<TProjectDetailDTO> tempList = queryAllowReadDetails(detailDTOS, param.getUserPhone(), param.getTenantCode());
            if(CollectionUtils.isEmpty(tempList)){
                return ReturnT.SUCCESS;
            }
            // 项目详情按照项目ID分组
            Map<String, List<TProjectDetailDTO>> detailMap = tempList.stream()
                    .collect(Collectors.groupingBy(item -> item.getProjectId()));
            Set<String> projectIds = detailMap.keySet();
            // 分页查询项目列表
            QueryWrapper<TProjectDTO> projectWrapper = new QueryWrapper<>();
            if(Objects.nonNull(param.getProjectStatus())){
                projectWrapper.eq("project_status", param.getProjectStatus());
            }
            if(StringUtils.isNotBlank(param.getProjectNameLike())){
                projectWrapper.like("project_name", param.getProjectNameLike());
            }
            if(StringUtils.isNotBlank(param.getSortRule()) && "asc".equalsIgnoreCase(param.getSortRule())){
                projectWrapper.orderByAsc("project_id");
            }
            if(StringUtils.isNotBlank(param.getSortRule()) && "desc".equalsIgnoreCase(param.getSortRule())){
                projectWrapper.orderByDesc("project_id");
            }
            projectWrapper.eq("tenant_code", param.getTenantCode());
            projectWrapper.in("project_id", projectIds);
            Page<TProjectDTO> page = new Page<>(param.getPageNum(), param.getPageSize());
            IPage<TProjectDTO> projectList = tProjectMapper.selectPage(page, projectWrapper);
            return new ReturnT(projectList);
        }else{
            log.info("根据:【{}】查询项目详情结果是空", param);
        }
        return ReturnT.SUCCESS;
    }

    @Override
    public ReturnT projectList(ProjectQueryPO po) {
        UserContextHolder.setTenant(po.getTenantCode());
        // 第一版：产品确认先忽略权限，默认企业下所有用户看到的项目都一样
        /*User user = Application.getUserStore().getOrCacheUser(po.getUserPhone(),po.getTenantCode());
        if (ObjectUtil.isEmpty(user)){
            return new ReturnT(500, "查询项目为空");
        }*/
        // 查询销售合同
        Page<ProjectPageVO> page = new Page<>(po.getPageNum(), po.getPageSize());
        IPage<ProjectPageVO> dtoList = tProjectMapper.projectList(page, po, null);
        return new ReturnT(dtoList);
    }

    @Override
    public ReturnT projectCount(ProjectCountPO po) {
        JSONArray jsonArray = new JSONArray();
        UserContextHolder.setTenant(po.getTenantCode());
       /* User user = Application.getUserStore().getOrCacheUser(po.getUserPhone(),po.getTenantCode());
        if (ObjectUtil.isEmpty(user)){
            return new ReturnT(500, "查询项目为空");
        }*/
        po.setProjectPhase(0);
        Integer aProjectPhase = tProjectMapper.selectProjectCount(po, null);
        JSONObject json1 = new JSONObject();
        json1.put("key", "销售阶段");
        json1.put("value", aProjectPhase);
        po.setProjectPhase(1);
        Integer bProjectPhase = tProjectMapper.selectProjectCount(po, null);
        JSONObject json2 = new JSONObject();
        json2.put("key", "签约阶段");
        json2.put("value", bProjectPhase);
        po.setProjectPhase(2);
        Integer cProjectPhase = tProjectMapper.selectProjectCount(po, null);
        JSONObject json3 = new JSONObject();
        json3.put("key", "履约阶段");
        json3.put("value", cProjectPhase);
        po.setProjectPhase(3);
        Integer dProjectPhase = tProjectMapper.selectProjectCount(po, null);
        JSONObject json4 = new JSONObject();
        json4.put("key", "已终止");
        json4.put("value", dProjectPhase);
        po.setProjectPhase(4);
        Integer eProjectPhase = tProjectMapper.selectProjectCount(po, null);
        JSONObject json5 = new JSONObject();
        json5.put("key", "已完成");
        json5.put("value", eProjectPhase);
        jsonArray.add(json1);
        jsonArray.add(json2);
        jsonArray.add(json3);
        jsonArray.add(json4);
        jsonArray.add(json5);
        return new ReturnT(jsonArray);
    }

    @Override
    public ReturnT projectUpdate(ProjectUpdatePO po) {
        TProjectDTO dto = selectProjectByProjectId(po.getProjectId(),po.getTenantCode());
        if (ObjectUtil.isEmpty(dto)){
            return new ReturnT(500,"查询项目为空");
        }
        /*if (dto.getProjectPhase() == 3 || dto.getProjectPhase() == 4){
            log.info("----------------> 项目已终止/完成，不做项目信息的编辑");
            return new ReturnT(500,"项目已终止/完成，不可编辑项目信息");
        }*/
        TProjectDTO projectDTO = new TProjectDTO();
        BeanUtils.copyProperties(po, projectDTO);
        projectDTO.setModifiedOn(new Date());
        int i= tProjectMapper.updateById(projectDTO);
        return i>0? ReturnT.SUCCESS:new ReturnT(500, "修改项目基本信息异常");
    }

    @Override
    public ReturnT projectDetail(ProjectQueryPO param) {
        QueryWrapper<TProjectDetailDTO> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("project_id", param.getProjectId());
        queryWrapper.orderByDesc("node_sort", "detail_id");
        queryWrapper.eq("tenant_code", param.getTenantCode());
        List<TProjectDetailDTO> detailDTOS = tProjectDetailMapper.selectList(queryWrapper);
        // 筛选可以访问的记录
        List<TProjectDetailDTO> tempList = queryAllowReadDetails(detailDTOS, param.getUserPhone(), param.getTenantCode());
        return new ReturnT(tempList);
    }

    @Override
    public TProjectDetailDTO selectByEntityId(String entityId, String tenantCode) {
        QueryWrapper<TProjectDetailDTO> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("entity_id", entityId);
        queryWrapper.eq("tenant_code", tenantCode);
        List<TProjectDetailDTO> detailDTOS = tProjectDetailMapper.selectList(queryWrapper);
        return CollectionUtils.isEmpty(detailDTOS) ? null : detailDTOS.get(0);
    }

    @Override
    public TProjectDTO selectProjectByProjectId(String entityId, String tenantCode) {
        QueryWrapper<TProjectDTO> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("project_id", entityId);
        queryWrapper.eq("tenant_code", tenantCode);
        TProjectDTO dto = tProjectMapper.selectOne(queryWrapper);
        return dto;
    }

    @Override
    @Transactional
    public void initProject(ProjectAddPO param) {
        String projectId = IdUtil.simpleUUID();
        TProjectDTO projectDTO = new TProjectDTO();
        projectDTO.setProjectId(projectId);
        BeanUtils.copyProperties(param, projectDTO);
        projectDTO.setCreatedBy(param.getCreatedBy());
        projectDTO.setModifiedBy(param.getCreatedBy());
        log.info("1，初始化项目：保存项目表");
        tProjectMapper.insert(projectDTO);
        TProjectDetailDTO detailDTO = new TProjectDetailDTO();
        detailDTO.setProjectId(projectId);
        BeanUtils.copyProperties(param, detailDTO);
        log.info("2，初始化项目：保存项目明细表");
        tProjectDetailMapper.insert(detailDTO);
        // 保存项目用户关系表
        TProjectUserDTO userDTO = new TProjectUserDTO();
        String configId = IdUtil.simpleUUID();
        userDTO.setConfigId(configId);
        userDTO.setProjectCode(projectId);
        userDTO.setEntityId(param.getEntityId());
        userDTO.setMembers(param.getCreatedBy());
        userDTO.setConfigType("CREATE");
        userDTO.setCreatedBy(param.getCreatedBy());
        userDTO.setModifiedBy(param.getCreatedBy());
        log.info("3，初始化项目：保存项目用户关系表");
        tProjectUserlMapper.insert(userDTO);
    }

    /**
     * 分派（分派只能是一个）
     *     1，先删除 根据项目编号，数据ID，分派标识查询到的旧数据
     *     2，新增分派的项目用户数据
     * 共享（共享给多人）
     *     1，先根据项目编号，数据ID，共享标识，for循环的当前人 查询数据是否存在
     *     2，不存在则新增数据，存在无需修改
     * @param param
     */
    @Override
    public void addProjectUser(ProjectUserPO param) {
        if (param.getConfigType().equalsIgnoreCase("ASSIGN")){
            tProjectUserlMapper.delete(new QueryWrapper<TProjectUserDTO>()
                    .eq("project_code", param.getProjectCode())
                    .eq("entity_id", param.getEntityId())
                    .eq("config_type", param.getConfigType())
                );
            for (String member:param.getMembers()) {
                // 保存项目用户关系表
                TProjectUserDTO userDTO = new TProjectUserDTO();
                String configId = IdUtil.simpleUUID();
                userDTO.setConfigId(configId);
                userDTO.setProjectCode(param.getProjectCode());
                userDTO.setEntityId(param.getEntityId());
                userDTO.setMembers(member);
                userDTO.setConfigType(param.getConfigType());
                userDTO.setCreatedBy(member);
                userDTO.setModifiedBy(member);
                tProjectUserlMapper.insert(userDTO);
            }
        }else if (param.getConfigType().equalsIgnoreCase("SHARE")){
            // 查询操作的该实体对应的项目是否存在该用户，不存在则新增关系
            for (String member:param.getMembers()) {
                QueryWrapper<TProjectUserDTO> wrapper = new QueryWrapper();
                wrapper.eq("project_code", param.getProjectCode());
                wrapper.eq("members", member);
                wrapper.eq("config_type", param.getConfigType());
                wrapper.eq("entity_id", param.getEntityId());
                List<TProjectUserDTO> userDTOList = tProjectUserlMapper.selectList(wrapper);
                if (CollectionUtils.isEmpty(userDTOList)){
                    // 保存项目用户关系表
                    TProjectUserDTO userDTO = new TProjectUserDTO();
                    String configId = IdUtil.simpleUUID();
                    userDTO.setConfigId(configId);
                    userDTO.setConfigType(param.getConfigType());
                    userDTO.setProjectCode(param.getProjectCode());
                    userDTO.setEntityId(param.getEntityId());
                    userDTO.setMembers(member);
                    userDTO.setCreatedBy(member);
                    userDTO.setModifiedBy(member);
                    tProjectUserlMapper.insert(userDTO);
                }
            }
        }
    }

    @Override
    public void delProjectUser(ProjectUserPO param) {
        // 查询操作的该实体对应的项目是否存在该用户，存在则删除关系
        if (param.getAllFlag()){
            tProjectUserlMapper.delete(new QueryWrapper<TProjectUserDTO>()
                    .eq("project_code", param.getProjectCode()));
        }else {
            for (String member:param.getMembers()) {
                QueryWrapper<TProjectUserDTO> wrapper = new QueryWrapper();
                wrapper.eq("project_code", param.getProjectCode());
                wrapper.eq("CONFIG_TYPE", "SHARE");
                wrapper.eq("members", member);
                List<TProjectUserDTO> userDTOList = tProjectUserlMapper.selectList(wrapper);
                if (!CollectionUtils.isEmpty(userDTOList)){
                    for (TProjectUserDTO userDTO:userDTOList) {
                        tProjectUserlMapper.deleteById(userDTO.getConfigId());
                    }
                }
            }
        }
    }

    @Override
    public void addProjectDetail(ProjectAndDetailUpdatePO param, String projectId) {
        TProjectDetailDTO detailDTO = new TProjectDetailDTO();
        BeanUtils.copyProperties(param, detailDTO);
        detailDTO.setProjectId(projectId);
        tProjectDetailMapper.insert(detailDTO);
    }

    @Override
    public void deleteProjectDetail(List<String> entityIds, String tenantCode) {
        QueryWrapper<TProjectDetailDTO> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("entity_id", entityIds);
        queryWrapper.eq("tenant_code", tenantCode);
        tProjectDetailMapper.delete(queryWrapper);
    }

    @Override
    public void updateProjectAndDetail(ProjectAndDetailUpdatePO param) {
        TProjectDTO projectDTO = new TProjectDTO();
        BeanUtils.copyProperties(param, projectDTO);
        tProjectMapper.updateById(projectDTO);
        TProjectDetailDTO detailDTO = new TProjectDetailDTO();
        BeanUtils.copyProperties(param, detailDTO);
        tProjectDetailMapper.updateById(detailDTO);
    }

    @Override
    public ReturnT selectNiche(ProjectQueryRelatedPO param) {
        ProjectNicheVO vo = tProjectMapper.selectNiche(param);
        return new ReturnT(vo);
    }

    @Override
    public ReturnT selectCustomerInfo(ProjectQueryRelatedPO param) {
        // 根据项目ID+商机实体标识查询商机ID
        QueryWrapper<TProjectDetailDTO> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("project_id", param.getId());
        queryWrapper.eq("entity_code", "rbshangji4");
        queryWrapper.eq("tenant_code", param.getTenantCode());
        List<TProjectDetailDTO> detailDTOS = tProjectDetailMapper.selectList(queryWrapper);
        if (CollectionUtils.isEmpty(detailDTOS)){
            return ReturnT.SUCCESS;
        }
        param.setId(detailDTOS.get(0).getEntityId());
        ProjectCustomerVO customerVO = tProjectMapper.selectCustomerInfo(param);
        if (ObjectUtil.isEmpty(customerVO)){
            return ReturnT.SUCCESS;
        }
        List<ProjectContactVO> contactVOList = new ArrayList<>();
        // 访问
        String accessAddress = h5Url + "sihaikehu&id=" + customerVO.getAccountId();
        customerVO.setAccessAddress(accessAddress);
        if (StringUtils.isNotBlank(customerVO.getAccountId())){
            contactVOList = tProjectMapper.selectContactVOList(customerVO.getAccountId());
            if (!CollectionUtils.isEmpty(contactVOList)){
                for (ProjectContactVO contactVO:contactVOList) {
                    String contactAddress = h5Url + "rblianxiren5&id=" + contactVO.getContactId();
                    contactVO.setAccessAddress(contactAddress);
                }
            }
        }
        customerVO.setContactVOList(contactVOList);
        return new ReturnT(customerVO);
    }

    @Override
    public ReturnT selectEntityCodeList(ProjectQueryRelatedPO param, JSONArray navs) {
        String[] ignoreList = {"$PROJECT$", "$FILEMRG$"};
        JSONArray result = new JSONArray();
        for (Object obj:navs) {
            JSONObject dataObj = JSONObject.parseObject(obj.toString());
            // 忽略动态
            if (!Arrays.asList(ignoreList).contains(dataObj.getString("value"))){
                if (Objects.isNull(dataObj.get("sub"))){
                    JSONObject subO = new JSONObject();
                    subO.put("name", dataObj.getString("text"));
                    subO.put("value", dataObj.getString("value"));
                    result.add(subO);
                }else {
                    JSONArray subArray = dataObj.getJSONArray("sub");
                    for (Object obj1:subArray) {
                        JSONObject subO = new JSONObject();
                        JSONObject dataObj1 = JSONObject.parseObject(obj1.toString());
                        subO.put("name", dataObj1.getString("text"));
                        subO.put("value", dataObj1.get("value"));
                        result.add(subO);
                    }
                }
            }
        }
        // 根据模块查询该用户已有的功能权限码
        Iterator<Object> it = result.iterator();
        while(it.hasNext()){
            Object obj = it.next();
            JSONObject el = (JSONObject) obj;
            String value = el.getString("value");
            if (param.getModuleCode().equals("PLAN")){
                if (!PLAN_LIST.contains(value)){
                    it.remove();
                }
            }else if (param.getModuleCode().equals("CONTRACT")){
                if (!CONTRACT_LIST.contains(value)){
                    it.remove();
                }
            }else if (param.getModuleCode().equals("FINANCIAL")){
                if (!FINANCIAL_LIST.contains(value)){
                    it.remove();
                }
            }
        }
        return new ReturnT(result);
    }

    @Override
    public ReturnT selectApprovalList(ProjectQueryRelatedPO param, JSONArray navs) {
        JSONArray jsonResultArray = new JSONArray();
        String[] ignoreList = {"$FEEDS$","$PROJECT$", "$FILEMRG$"};
        JSONArray result = new JSONArray();
        String tenantCode = BootEnvironmentPostProcessor.getDefaultTenant();
        for (Object obj:navs) {
            JSONObject dataObj = JSONObject.parseObject(obj.toString());
            // 忽略动态
            if (!Arrays.asList(ignoreList).contains(dataObj.getString("value"))){
                if (Objects.isNull(dataObj.get("sub"))){
                    JSONObject subO = new JSONObject();
                    subO.put("name", dataObj.getString("text"));
                    subO.put("value", dataObj.getString("value"));
                    Entity useMain = MetadataHelper.getEntity(dataObj.getString("value"));
                    subO.put("code", useMain.getEntityCode());
                    subO.put("icon", iconConfigService.selectIconByCode(dataObj.getString("value"), tenantCode));
                    result.add(subO);
                }else {
                    JSONArray subArray = dataObj.getJSONArray("sub");
                    for (Object obj1:subArray) {
                        JSONObject subO = new JSONObject();
                        JSONObject dataObj1 = JSONObject.parseObject(obj1.toString());
                        subO.put("name", dataObj1.getString("text"));
                        subO.put("value", dataObj1.get("value"));
                        if (!Arrays.asList(ignoreList).contains(dataObj1.getString("value"))){
                            Entity useMain = MetadataHelper.getEntity(dataObj1.getString("value"));
                            subO.put("code", useMain.getEntityCode());
                        }else {
                            subO.put("code", 0);
                        }
                        subO.put("icon", iconConfigService.selectIconByCode(dataObj1.getString("value"), tenantCode));
                        result.add(subO);
                    }
                }
            }
        }
        // 查询有审批配置的实体
        Object[][] array = Application.createQueryNoFilter(
                "select belongEntity from RobotApprovalConfig where isDisabled = ? and tenantCode = ? ")
                .setParameter(1, false)
                .setParameter(2, param.getTenantCode())
                .array();
        List<String> arrayList  = new ArrayList<>();
        if (array.length >0){
            for (Object[] o :array){
                arrayList.add(o[0].toString());
            }
        }
        // 根据模块查询该用户已有的审批权限
        JSONArray arrayA = new JSONArray(); // 销售阶段申请
        JSONArray arrayB = new JSONArray(); // 合同及交付申请
        JSONArray arrayC = new JSONArray(); // 收/支申请
        JSONArray arrayD = new JSONArray(); // 其他审批
        Iterator<Object> it = result.iterator();
        while(it.hasNext()){
            Object obj = it.next();
            JSONObject el = (JSONObject) obj;
            String value = el.getString("value");
            if (SALE_APPROVAL_LIST.contains(value)){
                arrayA.add(el);
            }else if (DELIVERY_APPROVAL_LIST.contains(value)){
                arrayB.add(el);
            }else if (PAY_APPROVAL_LIST.contains(value)){
                arrayC.add(el);
            }else if (arrayList.contains(value)){
                arrayD.add(el);
            }
        }
        if (arrayA.size() >0){
            JSONObject jsonResult = new JSONObject();
            jsonResult.put("name", "销售阶段申请");
            jsonResult.put("value", arrayA);
            jsonResultArray.add(jsonResult);
        }
        if (arrayB.size() >0){
            JSONObject jsonResult = new JSONObject();
            jsonResult.put("name", "合同及交付申请");
            jsonResult.put("value", arrayB);
            jsonResultArray.add(jsonResult);
        }
        if (arrayC.size() >0){
            JSONObject jsonResult = new JSONObject();
            jsonResult.put("name", "收/支申请");
            jsonResult.put("value", arrayC);
            jsonResultArray.add(jsonResult);
        }
        if (arrayD.size() >0){
            JSONObject jsonResult = new JSONObject();
            jsonResult.put("name", "其他审批");
            jsonResult.put("value", arrayD);
            jsonResultArray.add(jsonResult);
        }
        return new ReturnT(jsonResultArray);
    }

    @Override
    public ReturnT selectEntityInfoList(ProjectQueryRelatedPO param) {
        ReturnT returnT = new ReturnT();
        Page<ProjectPageVO> page = new Page<>(param.getPageNum(), param.getPageSize());
        String entityCode = param.getEntityCode();
        // 根据项目ID+实体编码查询项目明细
        QueryWrapper<TProjectDetailDTO> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("project_id", param.getId());
        queryWrapper.eq("entity_code", entityCode);
        queryWrapper.eq("tenant_code", param.getTenantCode());
        List<TProjectDetailDTO> detailDTOS = tProjectDetailMapper.selectList(queryWrapper);
        if (CollectionUtils.isEmpty(detailDTOS)){
            return new ReturnT(new Object[1]);
        }
        List<String> idList = detailDTOS.stream().map(TProjectDetailDTO::getEntityId).collect(Collectors.toList());
        // in条件查询返回对应实体列表的数据
        switch (entityCode){
            case "shouqianxietong28":
                // 售前协同
                IPage<ProjectPreSaleCoordinationVO> adDataList = tProjectMapper.selectPreSaleCoordinationPage(page,param.getParamLike(),idList);
                returnT.setData(adDataList);
                break;
            case "toubiaoxietong":
                // 投标协同
                IPage<ProjectTenderTogetherVO> bDataList = tProjectMapper.selectTenderTogetherPage(page,param.getParamLike(),idList);
                returnT.setData(bDataList);
                break;
            case "baojiaxietong":
                // 报价协同
                IPage<ProjectQuotationTogetherVO> cDataList = tProjectMapper.selectQuotationTogetherPage(page,param.getParamLike(),idList);
                returnT.setData(cDataList);
                break;
            case "shouqianfangan":
                // 售前方案
                IPage<ProjectPrdSalesPlanVO> dDataList = tProjectMapper.selectPrdSalesPlanPage(page,param.getParamLike(),idList);
                returnT.setData(dDataList);
                break;
            case "Quotation":
                // 报价单
                IPage<ProjectQuotationVO> eDataList = tProjectMapper.selectQuotationPage(page,param.getParamLike(),idList);
                returnT.setData(eDataList);
                break;
            case "kuangjiaxieyi":
                // 框架协议（销售）
                IPage<ProjectContractVO> fDataList = tProjectMapper.selectSaleFrameworkAgreementPage(page,param.getParamLike(),idList);
                returnT.setData(fDataList);
                break;
            case "rbhetong0":
                // 项目合同（销售）
                IPage<ProjectContractVO> gDataList = tProjectMapper.selectSaleContractPage(page,param.getParamLike(),idList);
                returnT.setData(gDataList);
                break;
            case "buchongxieyixiaoshou":
                // 补充协议【销售】
                IPage<ProjectContractVO> hDataList = tProjectMapper.selectBuchongxieyiPage(page,param.getParamLike(),idList);
                returnT.setData(hDataList);
                break;
            case "kuangjiaxieyi85":
                // 框架协议（采购）
                IPage<ProjectContractVO> iDataList = tProjectMapper.selectPurFrameworkAgreementPage(page,param.getParamLike(),idList);
                returnT.setData(iDataList);
                break;
            case "xiangmuhetong":
                // 项目合同（采购）
                IPage<ProjectContractVO> jDataList = tProjectMapper.selectPurchaseContractPage(page,param.getParamLike(),idList);
                returnT.setData(jDataList);
                break;
            case "buchongxieyicaigou":
                // 补充协议【采购】
                IPage<ProjectContractVO> kDataList = tProjectMapper.selectPurchaseBuchongxieyiPage(page,param.getParamLike(),idList);
                returnT.setData(kDataList);
                break;
            case "huikuanjihua":
                // 回款计划
                IPage<ProjectCollectionPlanVO> lDataList = tProjectMapper.selectCollectionPlanPage(page,param.getParamLike(),idList);
                returnT.setData(lDataList);
                break;
            case "shoukuanliushui":
                // 收款流水
                IPage<ProjectCollectingWaterVO> mDataList = tProjectMapper.selectCollectingWaterPage(page,param.getParamLike(),idList);
                returnT.setData(mDataList);
                break;
            case "fukuanjihua":
                // 付款计划
                IPage<ProjectPaymentPlanVO> nDataList = tProjectMapper.selectPaymentPlanPage(page,param.getParamLike(),idList);
                returnT.setData(nDataList);
                break;
            case "rbfenyong3":
                // 分佣任务
                IPage<ProjectCommissionTaskVO> oDataList = tProjectMapper.selectCommissionTaskPage(page,param.getParamLike(),idList);
                returnT.setData(oDataList);
                break;
            case "xiangmujilineibu":
                // 项目激励
                IPage<ProjectProjectIncentiveVO> pDataList = tProjectMapper.selectProjectIncentivePage(page,param.getParamLike(),idList);
                returnT.setData(pDataList);
                break;
            case "caigoushijianguanli":
                // 采购事件
                IPage<ProjectPurchaseEventVO> qDataList = tProjectMapper.selectPurchaseEventPage(page,param.getParamLike(),idList);
                returnT.setData(qDataList);
                break;
            case "jiaofushijianguanli":
                // 交付事件
                IPage<ProjectDeliveryEventVO> rDataList = tProjectMapper.selectDeliveryEventPage(page,param.getParamLike(),idList);
                returnT.setData(rDataList);
                break;
            default:
                break;
        }
        return returnT;
    }

    @Override
    public ReturnT selectProjectReport(ProjectReportPO param) {
        String tenantCode = UserContextHolder.getTenant();
        List<TProjectReportDTO> reportDTOList = tProjectReportMapper.selectList(new QueryWrapper<TProjectReportDTO>()
                .eq("project_code", param.getProjectCode())
                .eq("tenant_code", tenantCode));
        return new ReturnT(reportDTOList);
    }

    public List<TProjectDetailDTO> queryAllowReadDetails(List<TProjectDetailDTO> detailDTOS, String userPhone, String tenantCode){
        List<TProjectDetailDTO> tempList = new ArrayList<>();
        User user;
        try{
            user = Application.getUserStore().getOrCacheUser(userPhone, tenantCode);
        }catch (NoMemberFoundException e){
            log.info("用户不存在--{} -- {}", userPhone, tenantCode);
            e.printStackTrace();
            return tempList;
        }
        for(TProjectDetailDTO detail : detailDTOS){
            if(!ID.isId(detail.getEntityId())){
                log.info("查询记录不存在--{}", detail.getEntityId());
                continue;
            }
            // 判断此记录是否能被用户访问
            Boolean allowRead = Application.getPrivilegesManager().allowRead(user.getId(), ID.valueOf(detail.getEntityId()));
            if(allowRead){
                tempList.add(detail);
            }
        }
        return tempList;
    }

    @Override
    public ReturnT balanceOfPayments(String projectNo) throws Exception{
        long startTime = System.currentTimeMillis();
        // 当前登录用户
        ID user = UserService.ADMIN_USER;
        Map<String, JSON> resultMap = new HashMap<>();
        // 1 查询销售合同列表
        CompletableFuture<Void> salesContractFuture = getRecord(user, "rbhetong0", resultMap, projectNo);
        // 2 查询项目类报销列表
        CompletableFuture<Void> projectReimbursementFuture = getRecord(user, "xiangmuleibaoxiaoshenpi", resultMap, projectNo);
        // 3 查询项目类付款列表
        CompletableFuture<Void> projectReceivableFuture = getRecord(user, "xiangmuleifukuan", resultMap, projectNo);
        // 4 查询采购合同
        CompletableFuture<Void> purchaseContractFuture = getRecord(user, "xiangmuhetong", resultMap, projectNo);
        // 5 回款单
        CompletableFuture<Void> paymentReceiptFuture = getRecord(user, "rbhuikuandan1", resultMap, projectNo);
        // 6 查询备件采购
        // 7 查询交付工单
        // 8 查询备件出库
        CompletableFuture.allOf(salesContractFuture, projectReimbursementFuture, projectReceivableFuture, purchaseContractFuture, paymentReceiptFuture).get();
        long endTime = System.currentTimeMillis();
        log.info("统计项目报表耗时:{}ms", (endTime - startTime));
        log.info("查询结果{}", JSONObject.toJSONString(resultMap));
        return new ReturnT();
    }

    /**
     * 拼接实体查询参数
     * @param user
     * @param entityName
     */
    private CompletableFuture<Void> getRecord(ID user, String entityName, Map<String, JSON> queryMap, JSONObject filter) {
        String tenantCode = UserContextHolder.getTenant();
        Entity entity = MetadataHelper.getEntity(entityName);
        JSONObject query = new JSONObject();
        query.put("advFilter", "");
        query.put("entity", entityName);
        query.put("fields", entity.getFieldNames());
        query.put("reload", Boolean.TRUE);
        query.put("filter", filter);
        CompletableFuture<Void> salesContract = CompletableFuture.runAsync(() -> {
            UserContextHolder.setTenant(tenantCode);
            DataListBuilder builder = new DataListBuilderImpl(query, user);
            queryMap.put(entityName, builder.getJSONResult());
        }, threadPoolTaskExecutor);
        return salesContract;
    }

    /**
     * 查询数据
     * @param user
     * @param entityName
     * @param queryMap
     */
    private CompletableFuture<Void> getRecord(ID user, String entityName, Map<String, JSON> queryMap, String projectNo) {
        JSONObject item = new JSONObject();
        item.put("index", 1);
        item.put("field", "xiangmubiaoshi");
        item.put("op", ParseHelper.EQ);
        item.put("value", projectNo);
        JSONArray items = new JSONArray();
        items.add(item);
        JSONObject filter = new JSONObject();
        filter.put("entity", entityName);
        filter.put("equation", "AND");
        filter.put("items", items);
        return getRecord(user, entityName, queryMap, filter);
    }


}
